// 语言链接性
// 另一种形式的链接性称为语言链接性,(language linking)也对函数有影响。

// 链接程序要求每个不同的函数拥有不同的符号名。
// 在C语言中，一个名称只对应一个函数，因此这很容易实现。
// 但是在C++中由于函数具有重载特性，必须将这些函数翻译成不同的符号名称,因此C++编译器执行"名称矫正"或者"名称修饰"。

// 如果想要在C++中使用C语言库中预编译的函数,如下面的例子:
// spiff(22);          // 想要从c语言预编译库中使用spiff(int)
// C语言中库文件中的符号名称是 "_spiff"
// C++约定查找的符号名称是"_spiff_i"
// 为了解决这样的问题,可以使用函数原型来指出要使用的约定

// extern "C" void spiff(int);     //使用C语言方式来进行约定函数原型
// extern "C++" void spiff(int);   //使用C++语言方式来进行约定函数原型
// extern void spiff(int);         //没有显式指定的,默认按C++方式进行约定

#include <iostream>
#include <cstring>
#include <string>
#include <new>
// 存储方案和动态分配
// 通常变压器使用三块，独立的内存一块用于静态变量一块用于自动变量，另外一块用于动态存储

// 动态内存
// 使用new或者malloc/calloc等分配的内存,其内存不受作用域和链接性规则控制

// 使用new运算符进行初始化
int main(void)
{
    int *number = new int(8); // 注意:这里的new运算符旨在开辟内存空间,所以请使用int* 进行接受, 而不是 int number = new int (10);

    // 当new失败的时候,现在将会引发异常std::bad_alloc,以前是返回空指针

    // new 和 delete 运算符的定义是这样的
    // void *operator new(std::size_t) ;
    // void *operator new[](std::size_t) ;
    // void operator delete(void *);
    // void operator delete[](void *);

    // size_t是一个typedef
    // int * pi = new int;  等同于  int * pi = new (sizeof (int));
    // int * pa = new int[40];   等同于   int *pa = new (sizeof(int) * 40);
    // delete pi;   等同于  delete (pi);

    // 定位new运算符
    // 如果你有足够的知识和意愿，可以为new和delete提供替换函数，并根据需要对其进行定制。
    // 程序员可能使用这种特性来设置其内存管理流程，通过需要处理特定地址进行访问的硬件或在特定位置创建对象

    // 如果要使用定位new特性，首先要包含头文件new,然后将new运算符用于提供了所需地址的参数; 除了需要指定参数以外，句法和常规new运算符相同。
    struct chaff
    {
        char address[30];
        int slag;
    };
    char buffer1[50];
    char buffer2[100]; 

    chaff *p1, *p2;
    int *p3, *p4;

    // 常规new
    p1 = new chaff;
    p3 = new int;
    // 定位new
    p2 = new (buffer1) chaff;           //意在从buffer1中分配出一个chaff空间
    p4 = new (buffer2) int [20];        //从buffer2中分配一个int[20]空间

    int *p5 =  new (buffer2) int [20];  //这样分配的内存和p4相同,如果需要分配与p4不同的块,请在buffer处加上偏移量: int *p5 = new (buffer + sizeof(int) * 20) int [20];
    // 重要! : 因为buffer2不是new出来的内存,他处于静态内存中,所以delete是不发起作用的,并且引发运行阶段错误;
    //         如果buffer是通过new进行分配的内存,就可以使用delete进行释放内存
    
    // delete[] p5;
    // 出现异常。
    // Unknown signal


}
